﻿using CQIE.JonJack.Models;
using CQIE.JonJack.Models.Tabels;
using CQIE.JonJack.SplLibraryService._IBooksService;
using CQIE.JonJack.UtilitySource;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Polly.Timeout;
using Polly;
using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace CQIE.JonJack.SplLibraryService.BooksServiceImpl
{
    public class BooksServiceImpl : IBooksService
    {
        private readonly _DbContext Db;
        private readonly IOptionsSnapshot<JWTSettings> jwtSettingsOpt;

        private IDistributedCache RedisCache;
        private readonly PollyServices pollyServices;
        private Policy<string> _policy;
        private AsyncTimeoutPolicy policy;
        private Policy<string> fallBackPolicy;
        private Policy<string> wrapPolicy;
        private Policy<string> circuiBreaker;


        public BooksServiceImpl(_DbContext db, IOptionsSnapshot<JWTSettings> jwtSettingsOpt, IDistributedCache redisCache, PollyServices pollyServices)
        {
            Db = db;
            this.jwtSettingsOpt = jwtSettingsOpt;

            RedisCache = redisCache;
            this.pollyServices = pollyServices;

            //执行polly操作
            //pollyServices.TestCircuitBreaker();
            //降级
            _policy = pollyServices.TestRetry2();//重试
            policy = pollyServices.TestTimeOut();//超时
            fallBackPolicy = pollyServices.TestFallback();//回退
            wrapPolicy = pollyServices.TestWrapPolicy();//组合策略
            circuiBreaker = pollyServices.TestWrapPolicy_2();//熔断降级
        }

        public bool BorrowBook(string bookId, string endTime,string schoolNumber)
        {
            circuiBreaker.Execute(() =>
            {
                var js = new
                {
                    bookId = bookId,
                    endTime = endTime,
                    schoolNumber= schoolNumber
                };

                // 建立队列工厂
                IConnectionFactory factory = new ConnectionFactory
                {
                    HostName = "127.0.0.1", // IP地址
                    Port = 5672, // 端口号
                    UserName = "guest", // 用户账号
                    Password = "guest" // 用户密码
                };

                // 创建连接对象和连接会话对象
                using (var connection = factory.CreateConnection())
                using (var channel = connection.CreateModel())
                {
                    // 项目A发送消息队列
                    channel.ExchangeDeclare(exchange: "public-exchange", type: "direct");

                    // 定义队列
                    string queueName = "login-queue";
                    channel.QueueDeclare(queueName, false, false, false, null);

                    // 发送消息到交换器
                    var severity = "loginRequest"; // 路由键
                    string message = JsonConvert.SerializeObject(js); // 队列中的消息
                    var body = Encoding.UTF8.GetBytes(message);

                    // 交换器与队列绑定
                    channel.QueueBind(queueName, "public-exchange", severity, null);

                    // 发送到队列
                    var properties = channel.CreateBasicProperties();
                    properties.Persistent = true;

                    channel.BasicPublish(exchange: "public-exchange",
                                         routingKey: severity,
                                         basicProperties: properties,
                                         body: body);

                    Console.WriteLine(" [x] Sent '{0}':'{1}'", severity, message);
                }

                return "Operation completed successfully.";
            });

            return true;

        }

        /// <summary>
        /// 图书注销
        /// </summary>
        /// <param name="bid"></param>
        /// <returns></returns>
        public bool destructBook(int bid)
        {
            bool res = true;

            circuiBreaker.Execute(() =>
            {
                // 建立队列工厂
                IConnectionFactory factory = new ConnectionFactory
                {
                    HostName = "127.0.0.1", // IP地址
                    Port = 5672, // 端口号
                    UserName = "guest", // 用户账号
                    Password = "guest" // 用户密码
                };

                try
                {
                    // 创建连接对象和连接会话对象
                    using (var connection = factory.CreateConnection())
                    using (var channel = connection.CreateModel())
                    {
                        // 项目A发送消息队列
                        channel.ExchangeDeclare(exchange: "public-exchange", type: "direct");

                        // 定义队列
                        string queueName = "booksRequest-queue";
                        channel.QueueDeclare(queueName, false, false, false, null);

                        // 发送消息到交换器
                        var severity = "booksRequest"; // 路由键
                        string message = bid.ToString(); // 队列中的消息
                        var body = Encoding.UTF8.GetBytes(message);

                        // 交换器与队列绑定
                        channel.QueueBind(queueName, "public-exchange", severity, null);

                        // 发送到队列
                        var properties = channel.CreateBasicProperties();
                        properties.Persistent = true;

                        channel.BasicPublish(exchange: "public-exchange",
                                             routingKey: severity,
                                             basicProperties: properties,
                                             body: body);

                        Console.WriteLine(" [x] Sent '{0}':'{1}'", severity, message);
                    }
                }
                catch (Exception ex)
                {
                    res = false;
                }

                return "Operation completed successfully.";
            });

            

            return res;
        }
        /// <summary>
        /// 新增图书
        /// </summary>
        /// <param name="newBook"></param>
        /// <returns></returns>
        public bool setNewBook(string newBook)
        {
            bool res = true;
            circuiBreaker.Execute(() =>
            {
                //创建连接工厂对象
                IConnectionFactory factory = new ConnectionFactory
                {
                    HostName = "127.0.0.1", //IP地址
                    Port = 5672, //端口号
                    UserName = "guest", //用户账号
                    Password = "guest" //用户密码
                };

                try
                {
                    //创建连接和通道
                    var connection1 = factory.CreateConnection();
                    var channel1 = connection1.CreateModel();

                    try
                    {
                        channel1.ExchangeDeclare(exchange: "public-exchange", type: "direct");

                        //定义队列
                        string queueName1 = "booksResponse-queue";
                        var queue = channel1.QueueDeclare(queueName1, false, false, false, null);

                        // 发送消息到交换器
                        var severity = "booksResponse"; // 路由键
                        string message = newBook;//队列中的消息
                        var body = Encoding.UTF8.GetBytes(message);

                        //交换器与队列绑定
                        channel1.QueueBind(queueName1, "public-exchange", severity, null);

                        //发送到队列
                        channel1.BasicPublish(exchange: "public-exchange",
                                              routingKey: severity,
                                              basicProperties: null,
                                              body: body);

                        Console.WriteLine(" [x] Sent '{0}':'{1}'", severity, message);
                    }
                    finally
                    {
                        //确保在退出前关闭连接和通道
                        channel1.Close();
                        connection1.Close();
                    }
                }
                catch
                {
                    res = false;
                }
                return "Operation completed successfully.";
            });
           
            return res;
        }

        public string getAllBorrowedBook(string schoolNumber)
        {

            string jsonString = "";

            circuiBreaker.Execute(() =>
            {
                User user = Db.User
               .Include(u => u.BorrowRecords)!
               .ThenInclude(b => b.Book)
               .Where(u => u.SchoolNumber == schoolNumber)
               .Single();

                List<BorrowRecord> borrowRecords = user.BorrowRecords.Where(b => b.ReturnTime > DateTime.Now).ToList();
                var js = borrowRecords.Select(b => new
                {
                    bookId = b.Book.Id,
                    bookName = b.Book.BookName,//书名
                    bookAuthor = b.Book.Author,//作者
                    beginTime = b.BorrowTime, //借书时间
                    endTime = b.ReturnTime,//还书时间
                });

                jsonString= JsonConvert.SerializeObject(js);

                return "Operation completed successfully.";
            });

           
            return jsonString;

        }

        public string getHistoryBook(string schoolNumber)
        {
            string jsonString = "";

            circuiBreaker.Execute(() =>
            {
                User user = Db.User.Where(u => u.SchoolNumber == schoolNumber)
                .Include(u => u.BookHistorys)!
                .ThenInclude(b => b.Book).Single();

                List<BookHistory> bookHistory = user.BookHistorys;
                var js = bookHistory.Select(b => new
                {
                    bookId = b.Book.Id,
                    bookName = b.Book.BookName,//书名
                    bookAuthor = b.Book.Author,//作者
                    borrowTime = b.BorrowTime, //借书时间
                });

                jsonString = JsonConvert.SerializeObject(js);

                return "Operation completed successfully.";
            });

            
            return jsonString;
        }

        public bool ReturnBook(string bookId, string stuNum)
        {
            circuiBreaker.Execute(() =>
            {
                var js = new
                {
                    bookId = bookId,
                    schoolNumber = stuNum
                };


                //创建连接工厂对象
                IConnectionFactory factory = new ConnectionFactory
                {
                    HostName = "127.0.0.1", //IP地址
                    Port = 5672, //端口号
                    UserName = "guest", //用户账号
                    Password = "guest" //用户密码
                };

                #region 项目B发送返回结果到队列
                //创建连接和通道
                var connection1 = factory.CreateConnection();
                var channel1 = connection1.CreateModel();

                try
                {
                    channel1.ExchangeDeclare(exchange: "public-exchange", type: "direct");

                    //定义队列
                    string queueName1 = "loginResponse-queue";
                    var queue = channel1.QueueDeclare(queueName1, false, false, false, null);

                    // 发送消息到交换器
                    var severity = "loginResponse"; // 路由键
                    string message = JsonConvert.SerializeObject(js);//队列中的消息
                    var body = Encoding.UTF8.GetBytes(message);

                    //交换器与队列绑定
                    channel1.QueueBind(queueName1, "public-exchange", severity, null);

                    //发送到队列
                    channel1.BasicPublish(exchange: "public-exchange",
                                          routingKey: severity,
                                          basicProperties: null,
                                          body: body);

                    Console.WriteLine(" [x] Sent '{0}':'{1}'", severity, message);
                }
                finally
                {
                    //确保在退出前关闭连接和通道
                    channel1.Close();
                    connection1.Close();
                }
                #endregion




               
                return "Operation completed successfully.";
            });

            return true;
        }

        public string StatisticsBook()
        {
            string jsonString = "";

            circuiBreaker.Execute(() =>
            {
                List<Book> books = Db.Books.Include(b => b.BorrowRecords).ToList();
                var js = new
                {
                    bookCount = books.Count,//图书总数
                    bookTotal = books.Sum(b => b.Inventory),//库存总数
                    bookBorrowedCount = Db.BorrowRecord.Count(),//借出去图书的和
                    bookClass = new
                    {
                        noval = books.Where(b => b.BookClass == "小说").Count(),//小说藏有量
                        prose = books.Where(b => b.BookClass == "散文").Count(),//散文藏有量
                        poetry = books.Where(b => b.BookClass == "诗集").Count(),//诗集藏有量

                        rnoval = Db.BorrowRecord.Include(b => b.Book).Count(b => b.Book.BookClass == "小说"),//小说借出数量
                        rprose = Db.BorrowRecord.Include(b => b.Book).Count(b => b.Book.BookClass == "散文"),//散文借出数量
                        rpoetry = Db.BorrowRecord.Include(b => b.Book).Count(b => b.Book.BookClass == "诗集"),//诗集借出数量
                    }

                };
                jsonString = JsonConvert.SerializeObject(js);

                return "Operation completed successfully.";
            });

            
            return jsonString;
        }
    }
}
